package com.atguigu.gulimall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.OrderItem;
import com.alipay.api.internal.util.AlipaySignature;
import com.atguigu.common.enums.OrderStatusEnum;
import com.atguigu.gulimall.order.domain.vo.AliPayNotifyResponse;
import com.atguigu.gulimall.order.entity.OrderEntity;
import com.atguigu.gulimall.order.entity.OrderItemEntity;
import com.atguigu.gulimall.order.entity.PaymentInfoEntity;
import com.atguigu.gulimall.order.service.OrderItemService;
import com.atguigu.gulimall.order.service.OrderPayService;
import com.atguigu.gulimall.order.service.OrderService;
import com.atguigu.gulimall.order.service.PaymentInfoService;
import com.atguigu.gulimall.order.utils.AlipayTradePagePay;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @Description
 * @Author lhj
 * @Date 2024/5/25 11:24
 */
@Slf4j
@Service
public class OrderPayServiceImpl implements OrderPayService {

    private String aliPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjb3+/tDaruUCkaLIxi75KxEooICkbdblafYCQFct2VHziutT8iZhXv2ZhW0beeizz3X+nnKXiv1ZTTQTREcwGBT7DCTRVe5GBy21KDCnFyYyFFQHstC4ErNJtkhV73vem4IKeVkfiQGw2TBqQsYjyMyFfsq7/rY0qe5DBskqtvfupJH99Z6rQmOPyc8O60+mjxdd70ZWic/kpeKqXCBroWENGcXVbWZcUvBAKi1gA2bMUvuLaOtEtpGzRzgC9Ox1HCXTo0+pooVahqHLb9TObL9CBJX50PAqUHB+19Qj1B66yTcYKQAG1NP720L82H9dtsiUkfHhmb9WuwUnL+AtrwIDAQAB";

    private String charSet = "UTF-8";

    private String signType = AlipayConstants.SIGN_TYPE_RSA2;
    
    @Autowired
    OrderService orderService;
    
    @Autowired
    AlipayTradePagePay alipayTradePagePay;
    
    @Autowired
    OrderItemService orderItemService;
    
    @Autowired
    PaymentInfoService paymentInfoService;
    
    @Override
    public String orderPay(String orderSn) {
        try {
            if (StringUtils.isBlank(orderSn)) {
                throw new IllegalArgumentException("订单号不能为空!");
            }
            OrderEntity order = orderService.getOrderByOrderSn(orderSn);
            if (order == null) {
                throw new IllegalArgumentException("该订单不存在!");
            }
            OrderItemEntity orderItemEntity = orderItemService.getLastOrderItemByOrderSn(order);
            String tradedPagePay = alipayTradePagePay.tradePagePay(orderSn, order.getTotalAmount().setScale(2, RoundingMode.UP).toString(), orderItemEntity.getSkuName());
            if (StringUtils.isBlank(tradedPagePay)) {
                log.error("支付宝支付失败!");
            }
            return tradedPagePay;
        } catch (IllegalArgumentException e) {
            log.info("orderPay exception e", e);
            return null;
        }
    }

    @Override
    public String payedNotify(AliPayNotifyResponse notifyResponse) {
        try {
            Map<String, String> paramsMap = JSONObject.parseObject(JSONObject.toJSONString(notifyResponse), new TypeReference<Map<String, String>>() {});
            //调用SDK验证签名
            boolean signVerified = false;
            try {
                signVerified = AlipaySignature.rsaCheckV1(paramsMap, aliPublicKey, charSet, signType);
            } catch (AlipayApiException e) {
                log.info("payedNotify rasCheckV1 paramsMap: {} exception",JSONObject.toJSONString(paramsMap), e);
                return "failure";
            }
            // TODO 验签失败则记录异常日志，并在response中返回failure.
            if(!signVerified) {
                return "failure";
            }
            // TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
            String tradeStatus = notifyResponse.getTradeStatus();
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                //修改订单状态为已支付
                OrderEntity order = orderService.getOrderByOrderSn(notifyResponse.getOutTradeNo());
                if (Objects.isNull(order)) {
                    throw new RuntimeException("订单不存在！");
                }
                OrderEntity updateOrder = new OrderEntity();
                updateOrder.setId(order.getId());
                updateOrder.setStatus(OrderStatusEnum.PAYED.getCode());
                orderService.updateById(updateOrder);
            }
            savePaymentInfo(notifyResponse);
            return "success";
        } catch (RuntimeException e) {
            log.error("payedNotify exception", e);
            return "failure";
        }
    }

    private boolean savePaymentInfo(AliPayNotifyResponse notifyResponse) {
        PaymentInfoEntity paymentInfo = buildPaymentInfo(notifyResponse);
        return paymentInfoService.save(paymentInfo);
    }

    private PaymentInfoEntity buildPaymentInfo(AliPayNotifyResponse notifyResponse) {
        return PaymentInfoEntity.builder()
                .orderSn(notifyResponse.getOutTradeNo())
                .alipayTradeNo(notifyResponse.getTradeNo())
                .subject(notifyResponse.getSubject())
                .paymentStatus(notifyResponse.getTradeStatus())
                .createTime(notifyResponse.getGmtPayment())
                .confirmTime(new Date())
                .callbackTime(notifyResponse.getNotifyTime())
                .build();
    }
}
